//============================================================================
// Name        : game_test.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include "../irr/core/Environment.h"
#include <irrlicht.h>
#include <thread/IThread.h>
#include "../irr/log/Log.h"
#include "../irr/xml/Tags/print.h"

#include <control/CKeyboardBindKontrol.h>
#include <control/IKeyEvent.h>
#include <object/WorldElement.h>
#include <object/ModelObject.h>
#include <object/MoveableObjects.h>
#include <control/CKeyboardControl.h>
#include <scene/CDeltaTimeModule.h>
#include <scene/WOWCamera.h>
#include <object/AnimattedModelObject.h>
#include "../game-kernel/character/CharacterPattern.h"
#include "../game-kernel/character/CharacterSets.h"
#include "../game-kernel/character/body/CharacterModel.h"
#include "../game-kernel/FileLoader.h"
#include <image/CompositeImage.h>
#include <events/ClickListener.h>
#include <events/DestroyEmitter.h>
#include <object/LoadControllerListed.h>
#include <IDynVariable.h>
#include <StringUtils.h>
#include "../game-kernel/StaticModelObject.h"
#include <io/SceneLoader.h>
#include <xml/Tags/loadable.h>
#include <events/IRenderListener.h>
#include <scene/LoadableObjectList.h>
#include <scene/ISceneNodeLoadable.h>
#include <boost/thread/thread.hpp>
#include <events/IDestroyListener.h>
//#include <GL/glxew.h>
#include <GL/glx.h>
#include <GL/gl.h>
#include <debug_new/debug_new.h>

using namespace std;
using namespace irr;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

ISceneManager*smgr;

class MyLoadControl:public LoadControllerListed{
protected:
	/***
	 * Должена проверять объект на загруженность
	 *
	 * @param obj указатель на объект
	 * @param index номер объекта
	 * */
	virtual void checkObject(LoadControlledObject*obj,irr::u32 index){
		irr::f32 dis=obj->getPosition().getDistanceFromSQ(smgr->getActiveCamera()->getPosition());
		if (dis>30*30 && obj->isLoaded())
			obj->unload();

		if (dis<30*30 && obj->isUnloaded())
			obj->load();
	}
};

class myClick:public irr::gui::ClickListener{
public:
	bool onClick(void*Sender){
		LOG("CLICK!!!");
		return true;
	}
};


IrrlichtDevice *my_device;
irr::control::CKeyboardControl*mvoeControl;
irr::scene::CDeltaTimeModule*timeModul;
irr::animation::IAnimation*def_animation;
/*
class MyShaderCallBack : public irr::video::IShaderConstantSetCallBack{
public:
	virtual void OnSetConstants(irr::video::IMaterialRendererServices* services,irr::s32 userData){
	    int layer0 = 0;
	    int layer1 = 1;
	    services->setPixelShaderConstant("splatMap",(float*)&layer0,1);
	    services->setPixelShaderConstant("layer_red",(float*)&layer1,1);
	}
};
*/
void runXML(irr::io::path file){
	irr::xml::IXmlNode*node=my_device->getFactoryEnvironment()->getXmlTree("/home/caffeine/PF/northstar/Debug/data/human/x.xml");
	if (!node){
		LOG("Can't get NODE");
		exit(0);
	}
	my_device->getFactoryEnvironment()->runNode(node);
	node->drop();
}


/*
class GameModel:public irr::object::AnimattedModelObject{
private:
	//irr::scene::ISceneNode*node;
	irr::scene::IAnimatedMeshSceneNode*node;
protected:
	virtual void on_model_load(irr::scene::ISceneNode*parent){
		node=smgr->addAnimatedMeshSceneNode(smgr->getMesh("/home/caffeine/workspace/game_test/Debug/data/animation/skelet.x"),parent);
		node->setDebugDataVisible(EDS_FULL);
		def_animation->useAnimation(node);
		//node=smgr->addCubeSceneNode(10,parent);
		//LOG("LOAD MODEL");
		LOG("try get XML tree...");
		irr::xml::IXmlNode*node=my_device->getFactoryEnvironment()->getXmlTree("/home/caffeine/workspace/game_test/Debug/data/human/x.xml");
		if (!node){
			LOG("Can't get NODE");
			exit(0);
		}
		LOG("try run XML...");
		my_device->getFactoryEnvironment()->runNode(node);
		LOG("DONE! try drop XML");
		node->drop();
	}
	virtual void on_model_unload(){
		//LOG("UNLOAD MODEL");
		node->remove();
	}

	virtual void on_setCurrentAnimation(irr::animation::IAnimationRecord*record){
		LOG("on_setCurrentAnimation");
		if (record)
			record->useFor(node);
	}
	virtual void on_setAnimationGroup(irr::animation::IAnimation*group){
		LOG("on_setAnimationGroup");
		if (group)
			group->useAnimation(node);
		node->setLoopMode(true);
	}
public:
	GameModel(irr::IrrlichtDevice*my_device):irr::ILoadableObject(my_device),irr::object::AnimattedModelObject(0,0,my_device){
		//
	}
};
*/
class GameObject:public irr::object::WorldElement,public irr::object::MoveableObjects{
private:
	irr::f32 speed;
protected:
	virtual bool on_setPhysic(bool value){return false;};
	virtual void on_jump(irr::f32 value){};
public:
	GameObject(irr::scene::ISceneManager*manager,ContainerNodeObject*parent,bool sync_load):ContainerNodeObject(manager,parent),PositionObject(),PosittedContainerNodeObject(manager,parent),ModelLoaderObject(0,sync_load),irr::object::WorldElement(manager,parent,sync_load){
	}

	virtual void move(irr::f32 deltatime){
		setPosition(getPosition()+(getMoveDirection()*speed*deltatime));
	}

	virtual void onChangeMoveStatus(bool start){
		MARKER;
		if (start)
			LOG("START=TRUE");
		else
			LOG("START=FALSE");
		MARKER;
		irr::object::AnimattedModelObject*gm=(irr::object::AnimattedModelObject*)getModel();
		MARKER;
		if (start){
			MARKER;

			gm->setCurrentAnimation(gm->getAnimationGroup()->getAnimationByName("run"));
			MARKER;
		}else{
			MARKER;
			gm->setCurrentAnimation(gm->getAnimationGroup()->getAnimationByName("stand"));
			MARKER;
		}
		MARKER;
	}

	virtual void moveBack(irr::f32 deltatime){
		setPosition(getPosition()-(getMoveDirection()*speed*deltatime));
	}

	virtual void shiftLeft(irr::f32 deltatime){
		setPosition(getPosition()+(getShiftLeftDirection()*speed*deltatime));
	}

	virtual void shiftRight(irr::f32 deltatime){
		setPosition(getPosition()-(getShiftLeftDirection()*speed*deltatime));
	}

};

//irr::scene::ITextSceneNode*text;
//GameObject*obj;

class ObjectLoadControl:public irr::control::IKeyEvent{
public:
	virtual bool onKeyDown(EKEY_CODE key){
		//text->setText(L"DOWN");
		return true;
	}
	virtual bool onKeyUp(EKEY_CODE key){
		if (getDefaultLoadController()){
			while (getDefaultLoadController()->checkNext()){}
			getDefaultLoadController()->resetCheck();
		}
		//text->setText(L"UP");

		/*
		if (obj->isModelLoaded()){
			obj->unloadModel();
		}else{
			obj->loadModel();
		}
		*/
		return true;
	}
};

//IAnimatedMeshSceneNode* node=0;

irr::scene::ISkinnedMesh*m_mesh;
irr::scene::IAnimatedMeshSceneNode*m_node;


IGUIEnvironment* guienv;

irr::animation::IAnimation*def;
irr::control::CKeyboardBindKontrol*keyControl;



class GameReceiver:public irr::IEventReceiver{
public:
	virtual bool OnEvent(const SEvent& event){
		if (event.EventType==EET_KEY_INPUT_EVENT){
			if (event.KeyInput.PressedDown){
				if (mvoeControl->keyDown(event.KeyInput.Key))
					return true;
				return keyControl->onKeyDown(event.KeyInput.Key);
			}else{
				if (mvoeControl->keyUp(event.KeyInput.Key))
					return true;
				return keyControl->onKeyUp(event.KeyInput.Key);
			}
		}
		return false;
	}
};

GameReceiver gameReceiver;

class tLoader:public irr::thread::ITask{
public:
	virtual void run(){
		irr::thread::sleep(1000);
		/*
		if (!node)
			return;
		node->setPosition(irr::core::vector3df(0,2,0));
		node->setMaterialTexture( 0,
				my_device->getVideoDriver()->getTexture("sydney.bmp") );
		guienv->addStaticText(L"Hello World!",core::rect<s32>(10,10,260,22), true);
		//smgr->addCubeSceneNode(10);
		*/
		irr::thread::sleep(5000);
	}
};


bool a=false;
class CharackterVisualPropertyEditor:public irr::gui::ClickListener{
private:
	irr::gui::IGUIButton*back;
	irr::gui::IGUIButton*next;
	irr::gui::IGUIStaticText*text;
	irr::core::vector2di position;
	irr::u32 btn_size;
	irr::u32 txt_size;
	irr::u32 com_height;
	CharacterModel*model;
	CharacterSets sets;
	CharacterPattern::BodyElementType type;
public:
	void setPosition(irr::core::vector2di p){
		position=p;
		back->setRelativePosition(p);
		text->setRelativePosition(irr::core::vector2di(p.X+btn_size,p.Y));
		next->setRelativePosition(irr::core::vector2di(p.X+btn_size+txt_size,p.Y));
	}

	void setElementType(CharacterPattern::BodyElementType t){
		type=t;
	}

	CharackterVisualPropertyEditor(IGUIEnvironment*env){
		btn_size=50;
		txt_size=50;
		com_height=25;

		back=env->addButton(irr::core::rect<s32>(0,0,btn_size,com_height));
		next=env->addButton(irr::core::rect<s32>(0,0,btn_size,com_height));
		text=env->addStaticText(L"0",irr::core::rect<s32>(0,0,txt_size,com_height));

		//text->setAlignment(irr::gui::EGUIA_CENTER,irr::gui::EGUIA_CENTER,irr::gui::EGUIA_CENTER,irr::gui::EGUIA_CENTER);

		back->setText(L"<-");
		next->setText(L"->");
		text->setText(L"0");
		back->addListener(this);
		next->addListener(this);
	}

	bool onClick(void*Sender){
		if (Sender==back){
			if (sets.get(type)>0)
				sets.set(type,sets.get(type)-1);
			updateLabel();
		}else
		if (Sender==next){
			if (sets.get(type)+1<sets.parent->getGroups(type)->size())
				sets.set(type,sets.get(type)+1);
			updateLabel();
		}
		model->setVisual(sets);
		model->resetTexture();
		return true;
	}

	void setCharset(CharacterModel*cm){
		model=cm;
		sets=model->getVisual();
		updateLabel();
	}

	void updateLabel(){
		//sets.parent->getFace()
		//
		text->setText(irr::core::stringw(sets.get(type)).c_str());
	}
};
CharackterVisualPropertyEditor*faceEditor;
CharackterVisualPropertyEditor*facialEditor;
/*
class CLayoutShaderCallback : public IShaderConstantSetCallBack
{
    public:
        CLayoutShaderCallback(){};

        //Основная функция, непосредственно выполняющая передачу переменных
        void OnSetConstants(IMaterialRendererServices* services, s32 userData)
        {
            //Номера текстурных слоёв.
            int baseTexture = 0;
            int layer1Texture = 1;
            int layer2Texture = 2;
            int layer3Texture = 3;
            int layer4Texture = 4;
            int layer5Texture = 5;
            int mask123Texture = 6;
            int mask45Texture = 7;
            //Передаём адреса текстур в шейдер, указывая на имена переменных,
            //которые должны их получить.
            services->setPixelShaderConstant("baseMap",(float*)(&baseTexture),1);
            services->setPixelShaderConstant("layer1",(float*)(&layer1Texture),1);
            services->setPixelShaderConstant("layer2",(float*)(&layer2Texture),1);
            services->setPixelShaderConstant("layer3",(float*)(&layer3Texture),1);
            services->setPixelShaderConstant("layer4",(float*)(&layer4Texture),1);
            services->setPixelShaderConstant("layer5",(float*)(&layer5Texture),1);
            services->setPixelShaderConstant("mask123",(float*)(&mask123Texture),1);
            services->setPixelShaderConstant("mask45",(float*)(&mask45Texture),1);
        }
};
const int BMR=1;
const int BMRG=2;
const int BMRGB=3;
const int BMRGBMR=4;
const int BMRGBMRG=5;

	irr::s32 createLayoutShader(irr::IrrlichtDevice*device,irr::u8 layoutType){
	    io::path psFileName = "/home/caffeine/workspace/game_test/Debug/data/shader/frag.glsl"; //фрагментный (пиксельный) шейдер
		io::path vsFileName = "/home/caffeine/workspace/game_test/Debug/data/shader/vert.glsl"; //вертексный (вершинный) шейдер

		IGPUProgrammingServices* gpu = device->getVideoDriver()->getGPUProgrammingServices();


		irr::core::stringc vp="varying vec2 Texcoord;\nvarying vec2 Texcoord1;\nvoid main( void ){\ngl_Position = ftransform();\nTexcoord=gl_MultiTexCoord0.xy;\nTexcoord1=gl_MultiTexCoord1.xy;\n}";

		irr::core::stringc layout_variable="";
		for (irr::u32 i=1;i<=layoutType;i++)
			layout_variable+=irr::core::stringc("uniform sampler2D layer")+irr::core::stringc(i)+";\n";

		irr::core::stringc layout_variable_fun="";
		for (irr::u32 i=1;i<=layoutType;i++)
			layout_variable_fun+=irr::core::stringc("vec4 layer")+irr::core::stringc(i)+irr::core::stringc("C = texture2D( layer")+irr::core::stringc(i)+", Texcoord1 );\n";

		irr::core::stringc color1="";

		if (layoutType==BMR)
			color1="col = (layer1C-base)* mask1.r;\n";
		if (layoutType==BMRG)
			color1="col = (layer1C-base)* mask1.r + (layer2C-base)* mask1.g;\n";
		if (layoutType>=BMRGB)
			color1="col = (layer1C-base)* mask1.r + (layer2C-base)* mask1.g + (layer3C-base)* mask1.b;\n";

		irr::core::stringc color2="";
		if (layoutType==BMRGBMR)
			color2="col+=(layer4C-base)*mask2.r\n";
		if (layoutType==BMRGBMRG)
			color2="col+=(layer4C-base)*mask2.r+(layer5C-base)*mask2.g;\n";

		irr::core::stringc mask2="";
		irr::core::stringc mask2_variable="";
		if (layoutType>=BMRGBMR){
			mask2="uniform sampler2D mask45;\n";
			mask2_variable="vec4 mask2 = texture2D (mask45, Texcoord );\n";
		}



		irr::core::stringc fp=layout_variable+"uniform sampler2D baseMap;\n\
uniform sampler2D mask123;\n";
fp+=mask2+"\n\
varying vec2 Texcoord;\n\
varying vec2 Texcoord1;\n\
\n\
void main( void )\n\
{\n\
   vec4 base = texture2D( baseMap, Texcoord );\n\
   vec4 mask1 = texture2D (mask123, Texcoord );\n";
fp+=mask2_variable+"vec4 col;\n";

fp+=layout_variable_fun;
fp+=color1;
fp+=color2+"\
   base = base + col;\n\
   gl_FragColor = base;\n\
}";
		CLayoutShaderCallback* sC = new CLayoutShaderCallback();
		return gpu->addHighLevelShaderMaterial(vp.c_str(), "vertexMain", video::EVST_VS_1_1,fp.c_str(), "pixelMain", video::EPST_PS_1_1,sC, video::EMT_SOLID);
	}
*/

class LoadableSyncChecker:public irr::video::IRenderListener{
private:
	irr::u32 frame;
public:
	LoadableSyncChecker(){
		frame=0;
	}
	virtual bool onRenderAfter(void*Sender){
		frame++;
		if (frame<100)
			return false;
		frame=0;
		for (irr::u32 i=0;i<irr::getSizeLoadableSceneNodeList();i++)
			irr::getLoadableSceneNodeList(i)->initCheck();
		return true;
	};
};

class addLoadableUnSyncChecker:public irr::thread::ITask{
private:
	irr::thread::IThread*thread;
public:
	virtual void run(){
		while (!thread->isCanceled()){

		irr::thread::sleep(1000);
		for (irr::u32 i=0;i<irr::getSizeLoadableSceneNodeList();i++)
			irr::getLoadableSceneNodeList(i)->initCheck();
		LOG("Check load");
		}
	}
	void setThread(irr::thread::IThread*t){
		thread=t;
	}
};

class UnsyncLoadableChecker:public irr::thread::ITask,public virtual irr::IDestroyListener{
private:
	irr::IrrlichtDevice*device;
	irr::u32 timeInterval;
	irr::thread::IThread*thread;
public:

	virtual bool onDestroy(void*Sender){
		LOG("DESTOROY Device");
		return true;
	}

	UnsyncLoadableChecker(irr::IrrlichtDevice*d,irr::u32 ti=1000){
		device=d;
		timeInterval=ti;
		thread=device->createTaskThread(this);
		((irr::DestroyEmitter*)device)->giveDestroyListener(this);
	}

	void setCheckTimeInterval(irr::u32 ti){
		timeInterval=ti;
	}

	void setEnabled(bool enable){
		if (thread->isRunning() && !enable){
			thread->setCancel(true);
			thread->join();
		}

		if (!thread->isRunning() && enable){
			thread->setCancel(false);
			thread->start();
		}
	}

	~UnsyncLoadableChecker(){
		setEnabled(false);
		thread->drop();
		LOG("DESTOROY UnsyncLoadableChecker");
	}
	virtual void run(){
		while (!thread->isCanceled()){
			irr::thread::sleep(timeInterval);
			for (irr::u32 i=0;i<irr::getSizeLoadableSceneNodeList();i++)
				irr::getLoadableSceneNodeList(i)->initCheck();
		}
	}
};

void addLoadableSyncChecker(irr::IrrlichtDevice*device){
	LoadableSyncChecker*rl=new LoadableSyncChecker();
	device->getVideoDriver()->addRenderListener(rl);
	rl->drop();
}

MyLoadControl*loadControl;
irr::scene::IMeshSceneNode*cube=0;

void hello(){
	LOG("------------------------------------------------------");
	/*
	cube->setMaterialFlag(irr::video::EMF_LIGHTING,false);
	MARKER;
	irr::video::ITexture*t=my_device->getVideoDriver()->getTexture("/home/caffeine/brick_3.jpg");
	MARKER;
	cube->setMaterialTexture(0,t);
	MARKER;

	if (!glXMakeContextCurrent(glXGetCurrentDisplay(),glXGetCurrentDrawable(),glXGetCurrentDrawable(),glXGetCurrentContext())){
		LOG("ERROR: can't set current context!");
		return;
	}else
		LOG("Content is setted!");
	cube->setPosition(irr::core::vector3df(0,20,0));
	*/
	//my_device->getVideoDriver()->getTexture("/home/caffeine/brick_3.jpg");
	LOG("------------------------------------------------------");
}


class MyTask:public irr::thread::ITask{
public:
	virtual void run(){
		irr::thread::sleep(1000);
		my_device->setWindowCaption(irr::core::stringw(my_device->getVideoDriver()->getFPS()).c_str());

		//cube->setPosition(irr::core::vector3df(0,20,0));
		//cube->setMaterialTexture(0,my_device->getVideoDriver()->getTexture("/home/caffeine/brick_3.jpg"));
		//cube->setMaterialFlag(irr::video::EMF_LIGHTING,false);
	}
};

#define DEVICE_REF_PRINT LOG("device ref=%d",my_device->getReferenceCount())

int main(){


	irr::xml::IXmlNode*xml_node;
	my_device = createDevice( video::EDT_OPENGL,core::dimension2d<u32>(640, 480), 16,false, false, false, 0);
	my_device->closeDevice();
	my_device->drop();
	return 0;
	xml_node=my_device->getFactoryEnvironment()->getXmlTree("/home/caffeine/PF/northstar/Debug/data/test.scene");
	//my_device->getFactoryEnvironment()->runNode(ter);
	xml_node->drop();
	return 0;
	DEVICE_REF_PRINT;
	printf("Wait!\n");
	irr::thread::sleep(4000);
	for (int i=0;i<150000;i++){
	printf("----------------------------------------------------------------\n");
	xml_node=my_device->getFactoryEnvironment()->getXmlTree("/home/caffeine/PF/northstar/Debug/data/test.scene");
	//my_device->getFactoryEnvironment()->runNode(ter);
	xml_node->drop();
	printf("----------------------------------------------------------------\n");
	}
	printf("Wait!\n");
		irr::thread::sleep(10000);
	DEVICE_REF_PRINT;
	my_device->closeDevice();
	DEVICE_REF_PRINT;
	if (my_device->drop())
		printf("Removed!\n");
	else
		printf("Not removed!\n");


	return 0;

		loadControl=new MyLoadControl();
		setDefaultLoadController(loadControl);
		loadControl->drop();
		timeModul=new irr::scene::CDeltaTimeModule();
		keyControl=new irr::control::CKeyboardBindKontrol();
		keyControl->setBind(KEY_KEY_Q,new ObjectLoadControl());
		my_device = createDevice( video::EDT_OPENGL,core::dimension2d<u32>(640, 480), 16,false, false, false, 0);
		DEVICE_REF_PRINT;
		irr::animation::IAnimationDB*db=my_device->getSceneManager()->createSkinnedDBAnimation();
		irr::animation::setDefaultAnimationDB(db);
		DEVICE_REF_PRINT;
		db->drop();
		regPrint(my_device->getFactoryEnvironment());
		DEVICE_REF_PRINT;
		regLoadable(my_device->getFactoryEnvironment());
		DEVICE_REF_PRINT;
		regStaticModel(my_device->getFactoryEnvironment());
		DEVICE_REF_PRINT;
		FileLoader::setIrrDevice(my_device);
		DEVICE_REF_PRINT;
		IVideoDriver* driver = my_device->getVideoDriver();
		DEVICE_REF_PRINT;
		/*
		CompositeImage*img=new CompositeImage(my_device,irr::core::dimension2du(512,512));
		img->add(irr::core::position2di(10,10),"/home/caffeine/workspace/game_test/Debug/data/human/HumanMaleNakedPelvisSkin00_07.png");
		img->add(irr::core::position2di(10,10),"/home/caffeine/tmp/123.png");
		img->getTexture();
		driver->writeImageToFile(img->getStage(),"123.png");
		img->drop();
		return 0;
		*/

		my_device->setEventReceiver(&gameReceiver);
		DEVICE_REF_PRINT;
		regSceneLoader(my_device->getFileLoadMethods());
		DEVICE_REF_PRINT;
		if (!my_device) return 1;
		my_device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
		DEVICE_REF_PRINT;
		CharacterPattern::regFactory(my_device->getFactoryEnvironment());
		DEVICE_REF_PRINT;

		smgr = my_device->getSceneManager();

		//def_animation=smgr->createSkinnedAnimation("player");
		MARKER;
		//def_animation->addAnimationFromFile("/home/caffeine/workspace/game_test/Debug/data/animation/run.x","run");
		//def_animation->addAnimationFromFile("/home/caffeine/workspace/game_test/Debug/data/animation/stand.x","stand");
		MARKER;
		guienv = my_device->getGUIEnvironment();
		mvoeControl=new irr::control::CKeyboardControl();
		DEVICE_REF_PRINT;
		LOG("Load human model...");
		MARKER;
		runXML("/home/caffeine/PF/northstar/Debug/data/human/x.xml");
		DEVICE_REF_PRINT;
		MARKER;
		LOG("Loaded!");

		//obj=new GameObject(smgr,0,false);
		DEVICE_REF_PRINT;
		MARKER;
		CharacterPattern*cp=CharacterPattern::getPatternByID(1);
		MARKER;
		if (!cp){
			LOGE("ERROR: Character #1 not found!");
			exit(0);
		}
		MARKER;
		CharacterSets ps(cp);
		ps.set(CharacterPattern::BODY,0);
		ps.set(CharacterPattern::FEET,0);
		ps.set(CharacterPattern::HANDS,0);
		ps.set(CharacterPattern::FACE,1);
		DEVICE_REF_PRINT;
		MARKER;
		ps.parent=cp;
		ps.set(CharacterPattern::SKIN,0);
		ps.set(CharacterPattern::LAGS,0);
		ps.set(CharacterPattern::ADD,0);
		ps.set(CharacterPattern::FACIAL,0);
		DEVICE_REF_PRINT;
		//CharacterModel*character_model=new CharacterModel(my_device);
		DEVICE_REF_PRINT;
		//character_model->setLayoutTexture(CharacterModel::PANTS,"/home/caffeine/PF/northstar/Debug/data/HumanMaleNakedPelvisSkin00_00.png");
		DEVICE_REF_PRINT;
		//character_model->setLayoutTexture(CharacterModel::JACKET,"/home/caffeine/PF/northstar/Tabard_A_42GnomereganExiles_Chest.png");
		//character_model->setLayoutTexture(CharacterModel::BOOTS,"/home/caffeine/PF/northstar/Plate_Northrend_B_01Black_Boot.png");
		//character_model->setVisual(ps);
		DEVICE_REF_PRINT;
		//character_model->setAnimationGroup(irr::animation::getDefaultAnimationDB()->getByName("human"));
		DEVICE_REF_PRINT;
		//character_model->setAnimation(irr::animation::getDefaultAnimationDB()->getByName("human")->getAnimationByName("run"));
		DEVICE_REF_PRINT;
		//obj->giveModel(character_model);
		//mvoeControl->setMoveableObjects(obj);
		//face_back=guienv->addButton(irr::core::recti(0,0,50,25));
		//face_next=guienv->addButton(irr::core::recti(0,0,50,25));g
		MARKER;
		DEVICE_REF_PRINT;
		faceEditor=new CharackterVisualPropertyEditor(guienv);
		DEVICE_REF_PRINT;
		faceEditor->setElementType(CharacterPattern::FACE);
		//faceEditor->setCharset(character_model);
		faceEditor->setPosition(irr::core::vector2di(0,0));
		DEVICE_REF_PRINT;

		facialEditor=new CharackterVisualPropertyEditor(guienv);
		facialEditor->setElementType(CharacterPattern::FACIAL);
		//facialEditor->setCharset(character_model);
		facialEditor->setPosition(irr::core::vector2di(0,30));



		//guienv->addButton(irr::core::recti(0,0,100,50))->giveListener(new myClick());
		//def=smgr->createSkinnedAnimation("none");
		//smgr->getMesh("/home/caffeine/tmp/animation.x");
		//def->addAnimationFromFile("/home/caffeine/tmp/animation.x","one");


		//m_mesh=(irr::scene::ISkinnedMesh*)smgr->getMesh("/home/caffeine/tmp/model.x");
		//m_node=smgr->addAnimatedMeshSceneNode(m_mesh);
		//m_node->setDebugDataVisible(EDS_BBOX );
		//m_node->setScale(irr::core::vector3df(5,5,5));
		//def->useAnimation(m_node);

		//((irr::scene::ISkinnedMesh*)m_node->getMesh())->useAnimationFrom(def->getMesh());
		//m_mesh->useAnimationFrom(def->getMesh());
		//def->useFor("one",m_node);
		/*
		IAnimatedMesh* mesh = smgr->getMesh("sydney.md2");
		if (!mesh){
			my_device->drop();
			return 1;
		}
		node = smgr->addAnimatedMeshSceneNode(mesh);
		*/
		//node->setVisible(false);

/*
		if (node)
		{
			node->setMaterialFlag(EMF_LIGHTING, false);
			node->setMD2Animation(scene::EMAT_STAND);
		}
		*/
		//smgr->addCameraSceneNode(0, vector3df(0,30,-40),vector3df(0,5,0));
		//smgr->addCameraSceneNodeFPS();
		//MARKER;
		//text=smgr->addTextSceneNode(guienv->getFont("/home/caffeine/PF/northstar/Debug/data/fonts/console.xml"),L"Привет мир!");
		//MARKER;
		irr::xml::IXmlNode*ter;
		//ter=my_device->getFactoryEnvironment()->getXmlTree("/home/caffeine/PF/northstar/Debug/location.xml");
		//my_device->getFactoryEnvironment()->runNode(ter);
		//ter->drop();
		DEVICE_REF_PRINT;
		for (int i=0;i<150000;i++){
		ter=my_device->getFactoryEnvironment()->getXmlTree("/home/caffeine/PF/northstar/Debug/data/test.scene");
		//my_device->getFactoryEnvironment()->runNode(ter);
		ter->drop();
		}
		DEVICE_REF_PRINT;

		//MARKER;
		//ter->drop();
		//smgr->addTerrainSceneNode("/home/caffeine/workspace/game_linux/Debug/data/map/location1/h1.bmp");
/*
		MARKER;
		irr::scene::ITerrainSceneNode*terrain =smgr->addTerrainSceneNode(
	    		"/home/caffeine/h1.PNG",
	            0,                                      //родительский узел
	            -1,                                     //id узла
	            irr::core::vector3df(0.f, 0.f, 0.f),         //позиция
	            irr::core::vector3df(0.f, 0.f, 0.f),         //поворот
	            irr::core::vector3df(1.0f,1.0f,1.0f),//маштаб
	            irr::video::SColor ( 255, 255, 255, 255 ),   //цвет вершин
	            4,                                      //максимум LOD
	            irr::scene::ETPS_9,                         //размер патча
	            4,                                       //коэф-т размытия
	            true);



		if (terrain){
			/*
			LOG("MATERIAL COUNT=%d",(int)terrain->getMaterialCount());
			irr::io::IReadFile*img_file=my_device->getFileSystem()->createAndOpenFile("/home/caffeine/h1.PNG");
			terrain->loadHeightMap(img_file);
			img_file->drop();

		    //Настройка шейдера

			//irr::s32 shaderMaterialType = driver->getGPUProgrammingServices()->addLayoutShader(5);
			//terrain->scaleTexture(1.0f, 20.0f);
			//terrain->setMaterialFlag(EMF_LIGHTING, false);
			//driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS,false);
			//terrain->setMaterialType((E_MATERIAL_TYPE)shaderMaterialType);
			//terrain->getMaterial(0).MaterialType=(E_MATERIAL_TYPE)driver->getGPUProgrammingServices()->addLayoutShader(5);

			terrain->setMaterialTexture( 0, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/grass.jpg") );
	        terrain->setMaterialTexture( 1, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/sand.jpg") );
	        terrain->setMaterialTexture( 2, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/dirt.jpg") );
	        terrain->setMaterialTexture( 3, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/stone.jpg") );
	        terrain->setMaterialTexture( 4, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/lava.jpg") );
	        terrain->setMaterialTexture( 5, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/water.jpg") );
	        terrain->setMaterialTexture( 6, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/mask123.jpg") );
	        terrain->setMaterialTexture( 7, driver->getTexture("/home/caffeine/workspace/game_test/Debug/data/ter/mask45.jpg") );

			terrain->setDebugDataVisible(irr::scene::EDS_BBOX);
			//terrain->setVisible(false);
		}else
			LOG("TERRAIN not created!");

*/



		//addLoadableSyncChecker(my_device);
		//my_device->giveTaskAndRunThread(new addLoadableUnSyncChecker());
		int c=10;

		cube=my_device->getSceneManager()->addCubeSceneNode(10);


		DEVICE_REF_PRINT;
		WOWCamera*camera=new WOWCamera(smgr);
		camera->setEntity(cube);
		camera->setHeight(1.5);
		DEVICE_REF_PRINT;

		//my_device->giveTaskAndRunThread(new MyTask());
/*
		my_device->giveTaskAndRunThread(new irr::thread::ITask([]{
			irr::thread::sleep(1000);
			printf("-----------------GLERROR=%d\n",glGetError());

		}));
		*/
		//boost::thread thrd(&hello);

		UnsyncLoadableChecker*checker=new UnsyncLoadableChecker(my_device);
		//checker->setEnabled(true);

		/*
		my_device->giveTaskAndRunThread(new irr::thread::ITask([&](){
			cube->setMaterialFlag(irr::video::EMF_LIGHTING,false);
			irr::video::ITexture*t=my_device->getVideoDriver()->getTexture("/home/caffeine/brick_3.jpg");
			cube->setMaterialTexture(0,t);
		}));
		*/
		DEVICE_REF_PRINT;
		while(my_device->run()){

			timeModul->updateDeltatime(my_device->getTimer()->getTime());
			mvoeControl->step(timeModul->getDeltaTime());
			//if (!a){
				//my_device->giveTaskAndRunThread(new tLoader());
				//a=true;
			//}
			driver->beginScene(true, true, SColor(255,100,101,140));
			smgr->drawAll();
			guienv->drawAll();

			driver->endScene();

			while (getDefaultLoadController()->checkNext()){}
			getDefaultLoadController()->resetCheck();
		}
		DEVICE_REF_PRINT;
		setDefaultLoadController(0);
		//character_model->drop();
		DEVICE_REF_PRINT;
		checker->drop();
		faceEditor->drop();
		DEVICE_REF_PRINT;
		camera->drop();
		DEVICE_REF_PRINT;
		mvoeControl->drop();
		DEVICE_REF_PRINT;
		//obj->drop();
		DEVICE_REF_PRINT;
		my_device->drop();
		keyControl->drop();
		delete timeModul;

		irr::animation::setDefaultAnimationDB(0);

		delete faceEditor;
		delete facialEditor;

		my_device->drop();
		LOG("DONE!!!");
		return 0;
}
